package app.softtech.freechat;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

import org.apache.http.NameValuePair;
import org.apache.http.message.BasicNameValuePair;
import org.json.JSONException;
import org.json.JSONObject;

import com.google.android.gms.common.ConnectionResult;
import com.google.android.gms.common.GooglePlayServicesUtil;
import com.google.android.gms.gcm.GoogleCloudMessaging;

import android.app.Activity;
import android.app.AlertDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.SharedPreferences;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager.NameNotFoundException;
import android.graphics.Color;
import android.os.AsyncTask;
import android.os.Bundle;
import android.text.Editable;
import android.text.TextWatcher;
import android.util.Log;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.EditText;
import android.widget.Toast;
import app.softtech.freechat.database.DatabaseHanler;
import app.softtech.freechat.database.DatabaseUser;
import app.softtech.freechat.utils.ProjectUtils;

public class ActivityRegister extends Activity implements OnClickListener {
	static final String TAG = ActivityRegister.class.getName();

	private EditText mUsername, mPassword, mRepassword, mEmail, mPhoneNumber;
	private Button mRegister, mBackToLogin;

	String SENDER_ID = "202517753016";

	GoogleCloudMessaging gcm;
	Context context;
	String regid;
	String userid;
	String gcmType = "0";

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_register);
		
//		getGcmPreferences(getApplicationContext()).edit().clear().commit();
		
		mUsername = (EditText) findViewById(R.id.edt_username);
		mPassword = (EditText) findViewById(R.id.edt_password);
		mRepassword = (EditText) findViewById(R.id.edt_repassword);
		mEmail = (EditText) findViewById(R.id.edt_email);
		mPhoneNumber = (EditText) findViewById(R.id.edt_phonenumber);

		mRegister = (Button) findViewById(R.id.btn_register);
		mBackToLogin = (Button) findViewById(R.id.btn_back_to_login);
		
		context = getApplicationContext();
		if (checkPlayServices()) {
			gcm = GoogleCloudMessaging.getInstance(context);
			regid = getRegistrationId(context);

			if (regid.isEmpty()) {
				registerInBackground();
			} else {
				Log.i(TAG, "Device registered, registration ID = " + regid);
			}
		} else {
			Log.i(TAG, "No valid Google Play Services APK found.");
		}

		mRegister.setOnClickListener(this);
		mBackToLogin.setOnClickListener(this);

		setTextColorOfEditText(mUsername);
		setTextColorOfEditText(mPassword);
		setTextColorOfEditText(mRepassword);
		setTextColorOfEditText(mEmail);
		setTextColorOfEditText(mPhoneNumber);
	}

	@Override
	public boolean onCreateOptionsMenu(Menu menu) {
		// Inflate the menu; this adds items to the action bar if it is present.
		getMenuInflater().inflate(R.menu.activity_register, menu);
		return true;
	}

	@Override
	public boolean onOptionsItemSelected(MenuItem item) {
		// Handle action bar item clicks here. The action bar will
		// automatically handle clicks on the Home/Up button, so long
		// as you specify a parent activity in AndroidManifest.xml.
		int id = item.getItemId();
		if (id == R.id.action_settings) {
			return true;
		}
		return super.onOptionsItemSelected(item);
	}

	@Override
	public void onClick(View v) {
		if (v.getId() == R.id.btn_register) {
			String username = mUsername.getText().toString();
			String password = mPassword.getText().toString();
			String repassword = mRepassword.getText().toString();
			String email = mEmail.getText().toString();
			String phoneNumber = mPhoneNumber.getText().toString();
			register(username, password, repassword, email, phoneNumber);
		} else if (v.getId() == R.id.btn_back_to_login) {
			Intent i = new Intent(this, ActivityLogin.class);
			startActivity(i);
		}
	}

	/**
	 * Function to display alert dialog
	 * 
	 * @param context
	 *            - application context
	 * @param title
	 *            - alert title
	 * @param message
	 *            - alert message
	 * @param status
	 *            - success / failure (used to set icon)
	 */
	private void showAlertDialog(Context context, String title, String message, boolean status) {
		AlertDialog.Builder builder = new AlertDialog.Builder(context);

		builder.setTitle(title);
		builder.setMessage(message);
		builder.setIcon((status) ? R.drawable.ic_launcher : R.drawable.background_register);
		builder.setPositiveButton("OK", new DialogInterface.OnClickListener() {
			@Override
			public void onClick(DialogInterface dialog, int which) {

			}
		});

		AlertDialog alertDialog = builder.create();
		alertDialog.show();
	}

	/**
	 * Function to register an account to the server
	 * 
	 * @param username
	 * @param password
	 * @param repassword
	 * @param email
	 * @param phoneNumber
	 */
	@SuppressWarnings("unchecked")
	private void register(String username, String password, String repassword, String email, String phoneNumber) {
		List<NameValuePair> params = new ArrayList<NameValuePair>();

		params.add(new BasicNameValuePair(Constants.USERNAME, username));
		params.add(new BasicNameValuePair(Constants.PASSWORD, password));
		params.add(new BasicNameValuePair(Constants.EMAIL, email));
		params.add(new BasicNameValuePair(Constants.PHONE_NUMBER, phoneNumber));

		if (username.length() == 0) {
			mUsername.setTextColor(Color.RED);
			mUsername.setCompoundDrawablesWithIntrinsicBounds(0, 0, R.drawable.error, 0);
			return;
		}
		if (username.length() < 8) {
			mUsername.setTextColor(Color.RED);
			mUsername.setCompoundDrawablesWithIntrinsicBounds(0, 0, R.drawable.error, 0);
			return;
		}
		if (username.length() > 30) {
			mUsername.setTextColor(Color.RED);
			mUsername.setCompoundDrawablesWithIntrinsicBounds(0, 0, R.drawable.error, 0);
			return;
		}
		if (password.length() == 0) {
			mPassword.setTextColor(Color.RED);
			mPassword.setCompoundDrawablesWithIntrinsicBounds(0, 0, R.drawable.error, 0);
			return;
		}
		if (password.length() < 5) {
			mPassword.setTextColor(Color.RED);
			mPassword.setCompoundDrawablesWithIntrinsicBounds(0, 0, R.drawable.error, 0);
			return;
		}
		if (repassword.length() == 0) {
			mRepassword.setTextColor(Color.RED);
			mRepassword.setCompoundDrawablesWithIntrinsicBounds(0, 0, R.drawable.error, 0);
			return;
		}
		if (!password.equals(repassword)) {
			mRepassword.setTextColor(Color.RED);
			mRepassword.setCompoundDrawablesWithIntrinsicBounds(0, 0, R.drawable.error, 0);
			return;
		}
		if (email.length() == 0) {
			mEmail.setTextColor(Color.RED);
			mEmail.setCompoundDrawablesWithIntrinsicBounds(0, 0, R.drawable.error, 0);
			return;
		}
		if (email.length() < 8) {
			mEmail.setTextColor(Color.RED);
			mEmail.setCompoundDrawablesWithIntrinsicBounds(0, 0, R.drawable.error, 0);
			return;
		}
		if (email.length() > 30) {
			mEmail.setTextColor(Color.RED);
			mEmail.setCompoundDrawablesWithIntrinsicBounds(0, 0, R.drawable.error, 0);
			return;
		}
		if (phoneNumber.length() == 0) {
			mPhoneNumber.setTextColor(Color.RED);
			mPhoneNumber.setCompoundDrawablesWithIntrinsicBounds(0, 0, R.drawable.error, 0);
			return;
		}
		if (phoneNumber.length() < 4) {
			mPhoneNumber.setTextColor(Color.RED);
			mPhoneNumber.setCompoundDrawablesWithIntrinsicBounds(0, 0, R.drawable.error, 0);
			return;
		}

		/**
		 * 
		 */
		new AsyncTask<List<NameValuePair>, Void, Integer>() {

			/**
			 * return 0 - register failure return 1 - register successfully return 2 - email or user name already exists
			 */
			@Override
			protected Integer doInBackground(List<NameValuePair>... params) {
				HttpRequest request = new HttpRequest();
				String result = request.makeServiceCall(Constants.URL_REGISTER, HttpRequest.POST, params[0]);
				try {
					JSONObject jsonObj = new JSONObject(result);
					if (jsonObj.getString("success") != null) {
						String check = jsonObj.getString("success");
						if (Integer.parseInt(check) != 0) {
							storeUsername(params[0].get(0).getValue());
							userid = check;
							registerGcm(regid, userid, gcmType);
							DatabaseHanler db = new DatabaseHanler(getApplicationContext());
							db.insertDatabseUser(new DatabaseUser(Integer.parseInt(userid), params[0].get(0).getValue(),params[0].get(1).getValue(), params[0].get(2).getValue(), params[0].get(3).getValue(), "", 0, ""));
							Log.i(TAG, userid);
							return 1;
						} else if (Integer.parseInt(check) == 0) {
							String checkUsername = jsonObj.getString("username");
							String checkEmail = jsonObj.getString("email");
							if (Integer.parseInt(checkUsername) == 1 || Integer.parseInt(checkEmail) == 1) {
								return 2;
							}
						}
					} else {
						return 0;
					}
				} catch (JSONException e) {
					e.printStackTrace();
				}
				return 0;
			}

			@Override
			protected void onPostExecute(Integer result) {
				if (result == 1) {
					Toast.makeText(context, "Register successfully!", Toast.LENGTH_SHORT).show();
					Intent i = new Intent(getApplicationContext(), ActivityLogin.class);
					startActivity(i);
				} else if (result == 0) {
					showAlertDialog(ActivityRegister.this, "Register", "Register failed!", false);
				} else if (result == 2) {
					showAlertDialog(ActivityRegister.this, "Register", "Email or username already exists!", false);
				}
			}
		}.execute(params, null, null);
	}
	
	private void registerGcm(String regid, String userid, String gcmType){
		List<NameValuePair> params = new ArrayList<NameValuePair>();
		
		params.add(new BasicNameValuePair(Constants.PROPERTY_REG_ID, regid));
		params.add(new BasicNameValuePair(Constants.USER_ID, userid));
		params.add(new BasicNameValuePair(Constants.GCM_TYPE, gcmType));
		
		HttpRequest request = new HttpRequest();
		String result = request.makeServiceCall(Constants.URL_REGISTER_GCM, HttpRequest.POST, params);
		
		if(!result.isEmpty()){
			try {
				JSONObject jsonObj = new JSONObject(result);
				if(jsonObj != null){
				}
			} catch (JSONException e) {
				e.printStackTrace();
			}
		}
	}

	/**
	 * Function to store user name to shared preferences
	 * 
	 * @param username
	 */
	private void storeUsername(String username) {
		final SharedPreferences prefs = ProjectUtils.getPrefs(this, Constants.PROJECT_PREFS, Context.MODE_PRIVATE);
		SharedPreferences.Editor editor = prefs.edit();
		editor.putString(Constants.USERNAME, username);
		editor.commit();
	}

	/**
	 * 
	 * @param editText
	 */
	private void setTextColorOfEditText(final EditText editText) {

		editText.addTextChangedListener(new TextWatcher() {

			@Override
			public void onTextChanged(CharSequence s, int start, int before, int count) {
				if (editText.equals(mUsername) && s.length() >= 8) {
					setTextToBlackColor();
				}

				if (editText.equals(mPassword) && s.length() >= 5) {
					setTextToBlackColor();
				}

				if (editText.equals(mRepassword) && s.toString().equals(mPassword.getText().toString())) {
					setTextToBlackColor();
				}

				if (editText.equals(mEmail) && s.length() >= 8) {
					setTextToBlackColor();
				}

				if (editText.equals(mPhoneNumber) && s.length() >= 4) {
					setTextToBlackColor();
				}
			}

			@Override
			public void beforeTextChanged(CharSequence s, int start, int count, int after) {

			}

			@Override
			public void afterTextChanged(Editable s) {

			}

			/**
			 * 
			 */
			private void setTextToBlackColor() {
				editText.setTextColor(Color.BLACK);
				editText.setCompoundDrawablesWithIntrinsicBounds(0, 0, 0, 0);
				return;
			}
		});
	}
	
	/**
	 * @return Application's version code from the {@code PackageManager}.
	 */
	private static int getAppVersion(Context context) {
		try {
			PackageInfo packageInfo = context.getPackageManager().getPackageInfo(context.getPackageName(), 0);
			return packageInfo.versionCode;
		} catch (NameNotFoundException e) {
			// should never happen
			throw new RuntimeException("Could not get package name: " + e);
		}
	}

	/**
	 * Check the device to make sure it has the Google Play Services APK. If it doesn't, display a dialog that allows users to download the APK from the Google Play Store or enable it in the device's
	 * system settings.
	 */
	private boolean checkPlayServices() {
		int resultCode = GooglePlayServicesUtil.isGooglePlayServicesAvailable(this);
		if (resultCode != ConnectionResult.SUCCESS) {
			if (GooglePlayServicesUtil.isUserRecoverableError(resultCode)) {
				GooglePlayServicesUtil.getErrorDialog(resultCode, this, Constants.PLAY_SERVICES_RESOLUTION_REQUEST).show();
			} else {
				Log.i(TAG, "This device is not supported.");
				finish();
			}
			return false;
		}
		return true;
	}

	/**
	 * Stores the registration ID and the app versionCode in the application's {@code SharedPreferences}.
	 * 
	 * @param context - application's context.
	 * @param regId - registration ID
	 */
	private void storeRegistrationId(Context context, String regId) {
		final SharedPreferences prefs = getGcmPreferences(context);
		int appVersion = getAppVersion(context);
		Log.i(TAG, "Saving regId on app version " + appVersion);
		SharedPreferences.Editor editor = prefs.edit();
		editor.putString(Constants.PROPERTY_REG_ID, regId);
		editor.putInt(Constants.PROPERTY_APP_VERSION, appVersion);
		editor.commit();
	}

	/**
	 * Gets the current registration ID for application on GCM service, if there is one.
	 * <p>
	 * If result is empty, the app needs to register.
	 * 
	 * @return registration ID, or empty string if there is no existing registration ID.
	 */
	private String getRegistrationId(Context context) {
		final SharedPreferences prefs = getGcmPreferences(context);
		String registrationId = prefs.getString(Constants.PROPERTY_REG_ID, "");
		if (registrationId.isEmpty()) {
			Log.i(TAG, "Registration not found.");
			return "";
		}
		// Check if app was updated; if so, it must clear the registration ID
		// since the existing regID is not guaranteed to work with the new
		// app version.
		int registeredVersion = prefs.getInt(Constants.PROPERTY_APP_VERSION, Integer.MIN_VALUE);
		int currentVersion = getAppVersion(context);
		if (registeredVersion != currentVersion) {
			Log.i(TAG, "App version changed.");
			return "";
		}
		return registrationId;
	}

	/**
	 * Registers the application with GCM servers asynchronously.
	 * <p>
	 * Stores the registration ID and the app versionCode in the application's shared preferences.
	 */
	private void registerInBackground() {
		new AsyncTask<Void, Void, String>() {
			@Override
			protected String doInBackground(Void... params) {
				String msg = "";
				try {
					if (gcm == null) {
						gcm = GoogleCloudMessaging.getInstance(context);
					}
					regid = gcm.register(SENDER_ID);
					msg = "Device registered, registration ID = " + regid;

					// You should send the registration ID to your server over
					// HTTP, so it
					// can use GCM/HTTP or CCS to send messages to your app.
					sendRegistrationIdToBackend();

					// For this demo: we don't need to send it because the
					// device will send
					// upstream messages to a server that echo back the message
					// using the
					// 'from' address in the message.

					// Persist the regID - no need to register again.
					storeRegistrationId(context, regid);
				} catch (IOException ex) {
					msg = "Error :" + ex.getMessage();
					// If there is an error, don't just keep trying to register.
					// Require the user to click a button again, or perform
					// exponential back-off.
				}
				return msg;
			}

			@Override
			protected void onPostExecute(String msg) {
				Log.i(TAG, msg + "\n");
			}
		}.execute(null, null, null);
	}

	/**
	 * @return Application's {@code SharedPreferences}.
	 */
	private SharedPreferences getGcmPreferences(Context context) {
		// This sample app persists the registration ID in shared preferences,
		// but
		// how you store the regID in your app is up to you.
		return getSharedPreferences(Constants.PROJECT_PREFS, Context.MODE_PRIVATE);
	}

	private void sendRegistrationIdToBackend() {

	}
}
